// Player类是玩家基类，Human和AI是子类，它们要完成的功能有：
// -记录玩家类型，棋子颜色
// -记录玩家棋子在棋盘上的位置，用于判赢
// -落子

#ifndef PLAYER_H
#define PLAYER_H
#include <math.h>

#include <cstdlib>
#include <map>
#include <utility>

#include "board.h"

class Player  // 玩家基类
{
   protected:
    int type;      // 玩家类型，0为人类，1为AI
    int color;     // 玩家棋子颜色，-1为白，1为黑
    Board *board;  // *board指向当前棋盘

   public:
    Player() = default;       // 默认ctor
    int getType();            // 获取玩家类型：0为人类，1为AI
    int getColor();           // 获取玩家棋子颜色
    bool move(int x, int y);  // 落子函数，如果可以落子则返回true
    virtual ~Player();
    virtual std::pair<int, int> aiPick() = 0;  // AI选子纯虚函数
};

class Human : public Player  // 人类玩家子类
{
   public:
    Human() = default;
    Human(int _color, Board *board);  // ctor重载
    std::pair<int, int> aiPick() override;
};

class Ai : public Player  // AI子类
{
    int difficulty;
    std::pair<int, int> minBest;
    std::pair<int, int> maxBest;
    int startDepth;
    int numSearch;

   public:
    Ai() = default;
    Ai(int _color, int difficulty, Board *board);  // ctor重载
    std::map<std::string, int> blackPatterns;      // 黑棋模式串和其对应的估值
    std::map<std::string, int> whitePatterns;      // 白棋模式串和其对应的估值
    void initPatterns();                           // 初始化模式串
    std::pair<int, int> aiPick() override;         // 由AI选一个位置
    int getScore();                                // 当前棋盘的评估值

    // Utility functions
    char ntc(const int &n);                                                                // num to char 1 -> b, -1 -> w, 0 -> 0;
    int evaluate(const std::string &str, int color);                                       // 评估某一条链上的估值
    int minimax(const std::pair<int, int> &position, int depth, int a, int b, int color);  // 使用带ab剪枝的minimax算法搜索
    int KMPSearch(std::string pat, std::string txt);                                       // 使用KMP算法找到一条链中某种模式串的出现次数
    void computeLPSArray(std::string pat, int M, int lps[]);                               // KMP算法的一部分
};

#endif
